package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description DeviceServiceImpl
 * @Author CWJ
 * @Date 2025-05-19  18:26
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    // 注入阿里云client
    @Autowired
    private Client client;
    // AliIoTConfigProperties通常是用来加载和管理与阿里云IoT相关的配置属性的配置类
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;
    //  RedisTemplate用于操作Redis数据库
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public void syncProductList() {
        // TODO:实现从物联网平台同步产品列表的逻辑
        // 创建一个QueryProductListRequest对象，用于向物联网平台发送请求
        QueryProductListRequest request = new QueryProductListRequest();
        request.setPageSize(200);
        request.setCurrentPage(1);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        // TODO:处理从物联网平台获取的产品列表数据，并保存到数据库或缓存中
        //判断数据阿里云响应的数据是否为空的 如果为空则报错
        QueryProductListResponse response = null;
        try {
            response = client.queryProductList(request);
        } catch (Exception e) {
            // 如果发生异常，则抛出BaseException 响应码枚举
            throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }

        //接口是否调用成功,如果不成功抛出具体的错误信息
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }


        //获取数据，存储到redis
        //使用Stream流 将阿里云响应的信息收集成集合
        List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo().stream().map(
                p -> BeanUtil.toBean(p, ProductVo.class)
        ).collect(Collectors.toList());

        //存储到redis

        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));


    }

    /**
     * 查询所有产品列表
     *
     * @return 产品列表
     */
    @Override
    public List<ProductVo> allProuct() {
        //查询redis中键为iot.all_product的数据，也就是全部在阿里云中的全部数据 Json字符串
        String productListJsonStr = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
        if (ObjectUtil.isEmpty(productListJsonStr)) {
            //如果redis中没有数据，则直接返回空集合
            return Collections.emptyList();
        }
        //将集合转化为Json数据格式
        return JSONUtil.toList(productListJsonStr, ProductVo.class);
    }


    /**
     * 注册设备
     *
     * @param deviceDto 设备信息
     */
    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //检查设备名称是否重复 聚合函数查询设备名字
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        //如果重复 也就是count>0 返回状态码枚举
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //iot新增设备 获取阿里云的请求参数 同时获取我们的实例也就是实例id 物联网的实例id
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //使用client.registerDevice(registerDeviceRequest)发送设备注册请求
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        //接口是否调通 响应是否能成功
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        //根据productKey调用云查询产品信息，获取productName
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        QueryProductResponse queryProductResponse = null;
        //发送查询产品信息请求 拿取产品名称
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }

        //接口是否
        if (!queryProductResponse.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        //保存设备
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(response.getBody().getData().getIotId());
        device.setProductName(queryProductResponse.getBody().getData().getProductName());

        //如果设备绑定的位置是随身设备，则把物理绑定位置设置为-1
        if (device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())) {
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }


        deviceMapper.insertSelective(device);

    }


    /**
     * 分页查询设备
     *
     * @param devicePageQueryDto 分页查询参数
     * @return 设备列表
     */

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        Page<DeviceVo> deviceVos = deviceMapper.selectByPage(devicePageQueryDto);
        return PageResponse.of(deviceVos, DeviceVo.class);
    }

    //查询设备详情
    @Override
    public DeviceVo QueryDeviceDetail(QueryDeviceDetailRequest queryData) {
        queryData.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response = null;
        try {
            response = client.queryDeviceDetail(queryData);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断接口是否调通
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        //查询数据库的数据
        DeviceVo deviceVo = deviceMapper.selectByIotId(queryData.getIotId());

        //合并数据
        BeanUtil.copyProperties(response.getBody().getData(), deviceVo);

        return deviceVo;
    }


    /**
     * 查询指定产品的已发布物模型中的功能定义详情
     *
     * @param
     * @return
     */
    @Override
    public ResponseResult<QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData> queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response = null;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        return ResponseResult.success(response.getBody().getData());
    }
    // @Override
    // public ResponseResult<QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData> QueryThingModelPublished(QueryThingModelPublishedRequest request) {
    //     request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
    //     QueryThingModelPublishedResponse response = null;
    //     try {
    //         response = client.queryThingModelPublished(request);
    //     } catch (Exception e) {
    //         throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
    //     }
    //     if (!response.getBody().getSuccess()) {
    //         throw new RuntimeException(response.getBody().getErrorMessage());
    //     }
    //     return ResponseResult.success(response.getBody().getData());
    // }

    /**
     * 查询指定设备的物模型运行状态
     * @param
     * @return 设备状态
     */
    /**
     * 查询指定设备的物模型运行状态
     *
     * @param request 查询设备的物模型运行状态请求模型
     * @return 物模型运行状态
     */
    // @Override
    // public ResponseResult<QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData> queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
    //     request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
    //     QueryDevicePropertyStatusResponse response = null;
    //     try {
    //         response = client.queryDevicePropertyStatus(request);
    //     } catch (Exception e) {
    //         throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
    //     }
    //
    //     if (!response.getBody().getSuccess()) {
    //         throw new RuntimeException(response.getBody().getErrorMessage());
    //     }
    //     return ResponseResult.success(response.getBody().getData());
    // }}
    @Override
    public ResponseResult<QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData> queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response = null;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        return ResponseResult.success(response.getBody().getData());
    }

    /**
     * 修改设备信息
     * @param deviceDto 修改设备信息请求模型
     * @return 修改结果
     */

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //检验数据库是否存在设备
        Device dbDevice = deviceMapper.selectByPrimaryKey(deviceDto.getId());
        if(ObjectUtil.isEmpty(dbDevice)){
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }

        //保存位置
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        //如果是随身设备，物理位置设为-1
        if(device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        //更新数据库中设备信息
        deviceMapper.updateByPrimaryKeySelective(device);

        //调用物联网接口，更新云服务设备信息，这里只会更新阿里云那边的昵称，产品分类和设备名称一旦创建不允许再修改
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response = null;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

    }

    @Override
    public void deleteDevice(DeleteDeviceRequest request) {
        //删除数据库中设备信息
        deviceMapper.deleteByIotId(request.getIotId());

        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse response = null;
        try {
            response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
    }
}



